package com.zhai.netty.book.chapter02.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * 创建MultiPlexerTimerServer多路复用类
 * 他是一个独立的线程。负责轮询管道的selecter
 * 多路复用器：
 * 多路复用器，他是JavaNIO变成的基础，熟练的掌握Selector对于NIO编程至关重要
 * 多路复用器提供选择已经就绪的任务的能力
 * 简单来讲，Selector会不断的轮询注册再其上的Channel，如果某个Channel上面发生了读或者写事件
 * 这个channel就处于就绪状态，会被Selector轮询出来，然后通过SelectorKey可以获取就绪Channel集合
 *进行后续的I/O操作
 * @author 翟二远
 *
 */
public class MultiPlexerTimerServer implements Runnable{

	private Selector selector;
	
	private ServerSocketChannel serverSocketChannel;
	
	/**
	 * 当一个共享变量被volatile修饰时，它会保证修改的值立即被更新到主存
	 */
	private volatile boolean stop;
	
	MultiPlexerTimerServer(int port){
		try {
			selector = Selector.open(); //打开多路复用器
			serverSocketChannel = ServerSocketChannel.open(); //打开多路复用器下的管道
			serverSocketChannel.configureBlocking(false); //设置管道为非阻塞模式
			serverSocketChannel.socket().bind(new InetSocketAddress(port),1024);
			serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
			System.out.println("The Time Server Port is : "+port);
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}
	
	/**
	 * 设置停止方法
	 */
	public void stop(){
		this.stop = true;
	}
	
	public void run() {
		while(!stop){
			try {
				selector.select(1000);
				Set<SelectionKey> selectionKeys = selector.selectedKeys(); //获取有序的管道selectKeys
				Iterator<SelectionKey> iterator = selectionKeys.iterator(); //将selecterKeys添加到迭代器内方便对密钥组进行遍历
				
				SelectionKey selectionKey = null;
				while(iterator.hasNext()){
					selectionKey = iterator.next();
					iterator.remove();
					try {
						
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	private void handleInput(SelectionKey key) throws IOException{
		if(key.isValid()){
			if(key.isAcceptable()){
				//如果当前的selectionkey可接受的话
				SocketChannel sc = (SocketChannel) key.channel();
				if(key.isConnectable()){
					if(sc.finishConnect()){
						sc.register(selector, SelectionKey.OP_READ);
						
					}else {
						//链接失败，退出
						System.exit(1);
					}
				}
			}
		}
	}
	
	
	private void doWrite(SocketChannel sc) throws IOException{
		byte[] req = "QUITE TIME ORDER".getBytes();
		ByteBuffer writeBuffer = ByteBuffer.allocate(req.length);
		writeBuffer.put(req);
		writeBuffer.flip();
		sc.write(writeBuffer);
		if(!writeBuffer.hasRemaining()){
			System.out.println("Send order 2 server succeed.");
		}
	}

}
